إنشاء قائمتين منسدلتين (Dropdown Lists) باستخدام Laravel و jQuery: دليل شامل ومفصل
تُعد القوائم المنسدلة (Dropdown lists) من أكثر العناصر تفاعلية وانتشارًا في تصميم واجهات المستخدم على الويب، لما توفره من سهولة اختيار الخيارات وتقليل الفوضى في عرض البيانات. في كثير من التطبيقات الحديثة، هناك حاجة لربط قائمتين أو أكثر بطريقة ديناميكية، بحيث يتغير محتوى القائمة الثانية بناءً على اختيار المستخدم في القائمة الأولى. هذا النوع من التفاعل يساهم بشكل كبير في تحسين تجربة المستخدم، ويستخدم بكثرة في نماذج الإدخال المعقدة مثل اختيار الدولة ثم المدينة، أو اختيار القسم ثم المنتج، وغيرها من الحالات.
في هذا المقال، سنغطي بشكل مفصل كيف يمكن إنشاء قائمتين منسدلتين مرتبطتين باستخدام إطار العمل Laravel في جانب الخادم (Backend) و jQuery في جانب العميل (Frontend). سنتناول كل خطوة بشكل دقيق، مع التركيز على كتابة كود عملي، بالإضافة إلى شرح كل جزء لتسهيل الفهم والتنفيذ.
1. مقدمة عن Laravel و jQuery ودورهما في بناء القوائم المنسدلة الديناميكية
Laravel
يعتبر Laravel أحد أشهر أُطر العمل PHP لتطوير التطبيقات، حيث يوفر بنية حديثة، وأدوات قوية لتسهيل التعامل مع قواعد البيانات، التوجيه، المصادقة، وغيرها من الوظائف الأساسية. من مزاياه المهمة القدرة على بناء API أو نقاط نهاية (Endpoints) يمكن الوصول إليها عبر AJAX لتنفيذ استدعاءات ديناميكية دون الحاجة لإعادة تحميل الصفحة.
jQuery
jQuery هي مكتبة جافا سكريبت تُستخدم لتسهيل التعامل مع DOM، استدعاءات AJAX، إضافة التأثيرات، وغيرها من الوظائف. في هذا السياق، تُستخدم jQuery لجلب البيانات من الخادم ديناميكيًا وتحديث القائمة المنسدلة الثانية تلقائيًا بناءً على اختيار المستخدم في القائمة الأولى.
2. السيناريو المستخدم: قائمة منسدلة للدولة وقائمة منسدلة للمدينة
لنأخذ مثالًا عمليًا يعبر عن حالة شائعة: لدينا قائمة منسدلة للدول، وبناءً على الدولة المختارة، يتم عرض المدن التابعة لتلك الدولة في القائمة المنسدلة الثانية.
3. إعداد قاعدة البيانات
3.1 تصميم الجداول
سنحتاج إلى جدولين: countries و cities.
-
جدول countries
| الحقل | النوع | الوصف |
|---|---|---|
| id | INT (PK) | المعرف الأساسي |
| name | VARCHAR(255) | اسم الدولة |
| created_at | TIMESTAMP | وقت الإنشاء |
| updated_at | TIMESTAMP | وقت التحديث |
-
جدول cities
| الحقل | النوع | الوصف |
|---|---|---|
| id | INT (PK) | المعرف الأساسي |
| country_id | INT (FK) | معرف الدولة (مفتاح أجنبي) |
| name | VARCHAR(255) | اسم المدينة |
| created_at | TIMESTAMP | وقت الإنشاء |
| updated_at | TIMESTAMP | وقت التحديث |
3.2 إنشاء الهجرات (Migrations)
في Laravel، يتم إنشاء الهجرات باستخدام الأوامر التالية:
bashphp artisan make:migration create_countries_table --create=countries php artisan make:migration create_cities_table --create=cities
ثم نكتب محتوى الهجرات بالشكل التالي:
php// create_countries_table.php
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
// create_cities_table.php
public function up()
{
Schema::create('cities', function (Blueprint $table) {
$table->id();
$table->foreignId('country_id')->constrained()->onDelete('cascade');
$table->string('name');
$table->timestamps();
});
}
3.3 تشغيل الهجرات
لتنفيذ الهجرات وإنشاء الجداول:
bashphp artisan migrate
3.4 إدخال البيانات التجريبية
يمكن إدخال بيانات أولية عبر Seeder:
bashphp artisan make:seeder CountriesTableSeeder
ثم نكتب في Seeder:
phpuse Illuminate\Support\Facades\DB;
public function run()
{
DB::table('countries')->insert([
['name' => 'مصر'],
['name' => 'السعودية'],
['name' => 'الإمارات'],
]);
DB::table('cities')->insert([
['country_id' => 1, 'name' => 'القاهرة'],
['country_id' => 1, 'name' => 'الإسكندرية'],
['country_id' => 2, 'name' => 'الرياض'],
['country_id' => 2, 'name' => 'جدة'],
['country_id' => 3, 'name' => 'دبي'],
['country_id' => 3, 'name' => 'أبو ظبي'],
]);
}
ثم تنفيذ Seeder:
bashphp artisan db:seed --class=CountriesTableSeeder
4. إعداد النماذج (Models)
4.1 نموذج Country
phpnamespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
protected $fillable = ['name'];
public function cities()
{
return $this->hasMany(City::class);
}
}
4.2 نموذج City
phpnamespace App\Models;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
protected $fillable = ['name', 'country_id'];
public function country()
{
return $this->belongsTo(Country::class);
}
}
5. إنشاء الراوت (Routes) ووحدة التحكم (Controller)
5.1 تعريف الراوت
في ملف routes/web.php:
phpuse App\Http\Controllers\LocationController;
Route::get('/dropdown', [LocationController::class, 'index']);
Route::get('/get-cities/{country_id}', [LocationController::class, 'getCities']);
5.2 إنشاء وحدة التحكم
bashphp artisan make:controller LocationController
5.3 محتوى وحدة التحكم
phpnamespace App\Http\Controllers;
use App\Models\Country;
use App\Models\City;
use Illuminate\Http\Request;
class LocationController extends Controller
{
// عرض الصفحة التي تحتوي على القوائم المنسدلة
public function index()
{
$countries = Country::all();
return view('dropdown', compact('countries'));
}
// استرجاع المدن بناءً على معرف الدولة
public function getCities($country_id)
{
$cities = City::where('country_id', $country_id)->get();
return response()->json($cities);
}
}
6. إنشاء واجهة المستخدم (View) مع jQuery
6.1 ملف Blade: resources/views/dropdown.blade.php
htmlhtml>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>قائمتان منسدلتان ديناميكيتان باستخدام Laravel و jQuerytitle>
<script src="https://code.jquery.com/jquery-3.6.0.min.js">script>
head>
<body>
<h1>اختر الدولة والمدينةh1>
<label for="country">الدولة:label>
<select id="country" name="country">
<option value="">اختر الدولةoption>
@foreach($countries as $country)
<option value="{{ $country->id }}">{{ $country->name }}option>
@endforeach
select>
<br><br>
<label for="city">المدينة:label>
<select id="city" name="city" disabled>
<option value="">اختر المدينةoption>
select>
<script>
$(document).ready(function () {
$('#country').on('change', function () {
var countryID = $(this).val();
if (countryID) {
$.ajax({
url: '/get-cities/' + countryID,
type: "GET",
dataType: "json",
success: function (data) {
$('#city').empty();
$('#city').append('');
if(data.length > 0){
$.each(data, function (key, city) {
$('#city').append(' + '">' + city.name + '');
});
$('#city').prop('disabled', false);
} else {
$('#city').append('');
$('#city').prop('disabled', true);
}
},
error: function () {
$('#city').empty();
$('#city').append('');
$('#city').prop('disabled', true);
}
});
} else {
$('#city').empty();
$('#city').append('');
$('#city').prop('disabled', true);
}
});
});
script>
body>
html>
7. شرح الكود والآلية التفصيلية
7.1 تحميل الدول في القائمة الأولى
عند تحميل الصفحة، يقوم Controller بجلب جميع الدول من قاعدة البيانات وتمريرها إلى الـ Blade View، والتي تقوم بعرضها في الخاص بالدولة.
7.2 التعامل مع حدث تغيير اختيار الدولة
يتم الاستماع إلى حدث change على قائمة الدولة عبر jQuery، وعندما يختار المستخدم دولة معينة، يتم التقاط القيمة (ID) الخاصة بها.
7.3 استدعاء AJAX لجلب المدن
تقوم jQuery بإرسال طلب GET إلى نقطة النهاية /get-cities/{country_id} مع تمرير معرف الدولة. يستقبل Laravel هذا الطلب ويعيد Cities المتوافقة على شكل JSON.
7.4 تحديث القائمة الثانية بالمدن
بعد استلام البيانات، تقوم jQuery بتفريغ القائمة الحالية للمدن، ثم تعبئتها بالعناصر الجديدة بناءً على البيانات المستلمة. إذا لم تكن هناك مدن، تُعرض رسالة مناسبة وتعطّل القائمة.
7.5 التعامل مع الأخطاء
في حال فشل طلب AJAX لأي سبب، تعرض رسالة خطأ في القائمة وتُعطّل القائمة لمنع التفاعل الخاطئ.
8. تحسينات إضافية يمكن إضافتها
-
تفعيل الإرسال التلقائي: يمكن ربط القوائم بنموذج (form) ليتم الإرسال أوتوماتيكيًا بعد اختيار المدينة.
-
استخدام Select2 أو مكتبات أخرى: لتحسين تجربة المستخدم وتوفير خيارات بحث داخل القوائم المنسدلة.
-
دعم تحميل بيانات كبيرة: باستخدام التحميل التدريجي أو Pagination للمدن.
-
إضافة التحقق من صحة البيانات: على جانب الخادم للتأكد من أن المدينة المختارة تابعة للدولة المختارة.
-
استعمال API منفصلة: لفصل بين واجهة المستخدم وواجهة البيانات (REST API).
9. جدول مقارنة بين طرق بناء القوائم المنسدلة الديناميكية
| الطريقة | المميزات | العيوب |
|---|---|---|
| تحميل البيانات كاملةً مع الصفحة | لا يحتاج لاتصال إضافي بالخادم | زيادة حجم الصفحة، استهلاك بيانات غير ضروري |
| AJAX مع Laravel و jQuery | تحميل بيانات ديناميكي فقط عند الحاجة | يتطلب كتابة جافا سكريبت وتكوين نقاط نهاية API |
| استخدام Vue.js أو React | واجهات تفاعلية متقدمة وتجربة مستخدم سلسة | تعقيد أعلى، يتطلب تعلم إضافي |
10. الخلاصة
إن بناء قائمتين منسدلتين مرتبطتين باستخدام Laravel و jQuery هو حل عملي وفعال لتحسين تجربة المستخدم في تطبيقات الويب. تتيح هذه الطريقة تحميل بيانات القائمة الثانية ديناميكيًا بناءً على اختيار المستخدم في القائمة الأولى دون إعادة تحميل الصفحة، مما يوفر سرعة استجابة وتجربة تفاعلية أفضل. بالاعتماد على الإمكانيات التي يقدمها Laravel لإنشاء نقاط نهاية (API) واستغلال قوة jQuery في التعامل مع DOM و AJAX، يصبح تنفيذ هذه الميزة أمرًا بديهيًا وميسورًا. كما أن بناء المشروع بهذه الطريقة يفتح الباب لإضافة تحسينات متقدمة مستقبليًا، مثل استخدام مكتبات حديثة أو تنفيذ تدقيقات أمان معززة.
المصادر والمراجع
-
توثيق Laravel الرسمي: https://laravel.com/docs/10.x
-
توثيق jQuery الرسمي: https://api.jquery.com/
بهذا الشرح المفصل، يمكن لأي مطور العمل على بناء نظام قوائم منسدلة ديناميكية متكامل باستخدام Laravel و jQuery، مع فهم دقيق لكل جزء من العملية التقنية المطلوبة.

